package com.wolfsea.defineappframedemo
import android.content.Context
import android.util.AttributeSet
import android.util.Log
import android.view.LayoutInflater
import android.view.MotionEvent
import android.view.animation.DecelerateInterpolator
import android.widget.OverScroller
import android.widget.Scroller
import android.widget.Toast
import androidx.appcompat.widget.AppCompatImageView
import androidx.appcompat.widget.AppCompatTextView
import androidx.appcompat.widget.LinearLayoutCompat
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.core.view.get

/**
 *@desc  ContentItemLayout
 *@author liuliheng
 *@time 2022/12/1  22:58
 **/
class ContentItemLayout @JvmOverloads constructor(context: Context, attributeSet: AttributeSet? = null) :
    ConstraintLayout(context, attributeSet) {

    private var borderMarginValue = context.resources.getDimension(R.dimen.dp_10).toInt()

    private var calcTotalHeight = 0
    //可移动总高度
    private var movedTotalHeight = 0
    //已使用高度
    private var usedViewHeight = 0

    private var downX = 0
    private var downY = 0
    private var movedY = 0

    private val titleContentBorderMap = mutableMapOf<Int, Boolean>()
    private val itemMoveHeightMap = mutableMapOf<Int, Int>()

    private var mCallback: ICalcBelongedIndexCallback? = null

    private val mScroller by lazy {
        Scroller(context, DecelerateInterpolator())
    }

    override fun onFinishInflate() {
        super.onFinishInflate()

        val contentDataList = mutableListOf<ContentData>()

        val contentData0 = ContentData("红色",
            R.mipmap.ic_launcher,
            mutableListOf(
                "编程语言",
                "痛苦",
                "标准库",
                "避之不及",
                "想逃离",
                "运动少",
                "世界杯",
            ))

        val contentData1 = ContentData("蛋壳灰",
            R.mipmap.ic_launcher,
            mutableListOf(
                "情况",
                "元编程",
                "D语言",
                "质量",
                "编译器 ",
                "小问题 ",
                "累积起来 ",
                "内测 ",
                "请注意 ",
                "构建脚本 ",
                "更多错误 ",
                "我的期望 ",
            ))

        val contentData2 = ContentData("砖红",
            R.mipmap.ic_launcher,
            mutableListOf(
                "潜力",
                "正确选择",
                "适合我",
                "移植",
                "两个系统 ",
                "回放过程 ",
            ))

        val contentData3 = ContentData("青色",
            R.mipmap.ic_launcher,
            mutableListOf(
                "绘制的",
                "纯代码",
                "铺满整排",
            ))

        val contentData4 = ContentData("橘黄",
            R.mipmap.ic_launcher,
            mutableListOf(
                "公众号",
                "延期举行",
                "发布日期",
                "无人车",
                "签署",
                "关键",
                "应用商店",
                "可靠性",
                "腾讯",
                "蔚来",
                "智能驾驶",
                "抖音",
                "企业芯",
            ))

        val contentData5 = ContentData("棕色",
            R.mipmap.ic_launcher,
            mutableListOf(
                "核心业务",
                "Google",
                "欧洲",
                "数据统计",
                "智能手机",
                "预期",
                "绘画",
                "黑话"
            ))

        val contentData6 = ContentData("黄色",
            R.mipmap.ic_launcher,
            mutableListOf(
                "全面屏",
                "核心业务",
                "Spring",
                "组件",
                "金牌供应商",
                "参赛者",
                "交卷",
                "雷同代码",
                "咨询",
                "严重程度",
            ))

        val contentData7 = ContentData("胡紫色",
            R.mipmap.ic_launcher,
            mutableListOf(
                "两位大神",
                "皮肤",
                "置灰方案",
                "颜色矩阵",
                "饱和度",
                "数据变化",
                "重绘",
                "清明节",
                "阶段适配",
                "保护功能",
                "加密",
                "自研芯片",
                "开源",
            ))

        contentDataList.add(contentData0)
        contentDataList.add(contentData1)
        contentDataList.add(contentData2)
        contentDataList.add(contentData3)
        contentDataList.add(contentData4)
        contentDataList.add(contentData5)
        contentDataList.add(contentData6)
        contentDataList.add(contentData7)

        addContent(contentDataList)
    }

    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec)
        setMeasuredDimension(
            MeasureSpec.getSize(widthMeasureSpec) - paddingStart - paddingEnd,
            MeasureSpec.getSize(heightMeasureSpec) - paddingTop - paddingBottom
        )
    }

    override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) {

        if (childCount < 2) {
            return
        }
        val childView = get(1)
        val measureWidth = childView.measuredWidth
        borderMarginValue = (width - (ITEMS_PER_ROW) * measureWidth) / (ITEMS_PER_ROW + 1)

        //val itemPerWidth = (width - (ITEMS_PER_ROW + 1) * borderMarginValue) / ITEMS_PER_ROW

        var contentIndex = 0
        var itemMoveIndex = 0
        var totalHeight = 0
        for (i in 0.until(childCount)) {
            val condition = titleContentBorderMap[i] ?: false
            if (condition) {
                contentIndex = 0

                Log.d(TAG, "title->i:${i}")
                val titleView = get(i)
                val titleViewLayoutParam = titleView.layoutParams as ConstraintLayout.LayoutParams
                val titleViewWidth = titleView.measuredWidth
                val titleViewHeight = titleView.measuredHeight
                val marginStart = titleViewLayoutParam.marginStart
                val marginTop = titleViewLayoutParam.topMargin
                titleView.layout(
                    marginStart,
                    marginTop + totalHeight /*+ movedY*/,
                    marginStart + titleViewWidth,
                    marginTop + totalHeight + titleViewHeight/* + movedY*/
                )
                totalHeight += titleViewHeight + marginTop

                if (totalHeight <= height) {
                    usedViewHeight = totalHeight - marginTop - titleViewHeight
                }

                //第一个item移动高度为0
                if (i == 0) {
                    if (itemMoveHeightMap[itemMoveIndex] == null) {
                        itemMoveHeightMap[itemMoveIndex] = 0
                    }
                    itemMoveIndex++
                }
            } else {
                val contentView = get(i)
                val contentViewLayoutParam = contentView.layoutParams as ConstraintLayout.LayoutParams
                val marginTop = contentViewLayoutParam.topMargin
                val contentViewWidth = contentView.measuredWidth
                val contentViewHeight = contentView.measuredHeight

                if (contentIndex % ITEMS_PER_ROW == 0 && contentIndex >= ITEMS_PER_ROW) {
                    totalHeight += marginTop + contentViewHeight
                }

                if (totalHeight <= height) {
                    usedViewHeight = totalHeight - (marginTop + contentViewHeight)
                }

                val calIndex = contentIndex % ITEMS_PER_ROW

                contentView.layout(
                    (calIndex + 1) * borderMarginValue + contentViewWidth * calIndex,
                    marginTop + totalHeight /*+ movedY*/,
                    (calIndex + 1) * borderMarginValue + contentViewWidth * (calIndex + 1),
                    marginTop + totalHeight + contentViewHeight /*+ movedY*/
                )

                //contentView.layout(
                //    (calIndex + 1) * borderMarginValue + itemPerWidth * calIndex,
                //    marginTop + totalHeight + movedY,
                //    (calIndex + 1) * borderMarginValue + itemPerWidth * (calIndex + 1),
                //    marginTop + totalHeight + contentViewHeight + movedY
                //)
                //contentView.setOnClickListener {
                //    context.showToast("item:${i}")
                //}

                if ((i + 1) < childCount && titleContentBorderMap[i + 1]!!) {
                    totalHeight += marginTop + contentViewHeight
                    if (itemMoveHeightMap[itemMoveIndex] == null) {
                        itemMoveHeightMap[itemMoveIndex] = totalHeight
                    }
                    Log.d(TAG, "totalHeight:${totalHeight}")
                    itemMoveIndex++
                }

                contentIndex++

                if (totalHeight <= height) {
                    usedViewHeight = totalHeight - (marginTop + contentViewHeight)
                }
            }
        }

        calcTotalHeight = totalHeight
        movedTotalHeight = totalHeight - usedViewHeight
    }

    override fun onInterceptTouchEvent(ev: MotionEvent?): Boolean {
        when (ev?.action) {
            MotionEvent.ACTION_DOWN -> {
                downY = ev.y.toInt()
            }
            MotionEvent.ACTION_MOVE -> {
                val actionMoveY = ev.y.toInt()
                return if (Math.abs(downY - actionMoveY) >= MIN_SLIDE_DISTANCE) {
                    downY = actionMoveY
                    true
                } else {
                    downY = actionMoveY
                    false
                }
            }
        }
        return super.onInterceptTouchEvent(ev)
    }

    override fun onTouchEvent(event: MotionEvent?): Boolean {
        performClick()
        when (event?.action) {
            MotionEvent.ACTION_DOWN -> {
                if (!mScroller.isFinished) {
                    mScroller.abortAnimation()
                }
                downX = event.x.toInt()
                downY = event.y.toInt()
            }
            MotionEvent.ACTION_MOVE -> {
                val actionMoveX = event.x.toInt()
                val actionMoveY = event.y.toInt()
                val diffValue = actionMoveY - downY
                val totalMovedY = movedY
                if (Math.abs(diffValue) > Math.abs(actionMoveX - downX)) {
                    movedY += diffValue
                    movedY = if (diffValue > 0) {
                        //下滑
                        Math.min(0, movedY)
                    } else {
                        //上滑
                       Math.max(movedY, -movedTotalHeight)
                    }

                    val targetIndex = calcBelongedIndex(Math.abs(movedY)) - 1
                    mCallback?.calcBelongedIndex(targetIndex)
                    Log.d(TAG, "targetIndex:${targetIndex}")
                }
                //scrollTo(0, -movedY)
                mScroller.startScroll(mScroller.finalX, -totalMovedY, mScroller.finalX, diffValue)
                invalidate()

                //requestLayout()
                downX = actionMoveX
                downY = actionMoveY
            }
            MotionEvent.ACTION_UP -> {
                val startY = -movedY
                val targetY = -movedY
                mScroller.startScroll(mScroller.finalX, startY, mScroller.finalX, targetY - startY)
                invalidate()
            }
        }
        return true
    }

    override fun computeScroll() {
        super.computeScroll()
        if (mScroller.computeScrollOffset()) {
            scrollTo(mScroller.currX, mScroller.currY)
            invalidate()
        }
    }

    override fun performClick(): Boolean {
        return super.performClick()
    }


    private fun calcBelongedIndex(movedY: Int): Int {
        var targetIndex = -1
        for ((index, itemHeight) in itemMoveHeightMap) {
            if (movedY < itemHeight) {
                targetIndex = index
                break
            }
        }
        return targetIndex
    }

    fun skip2Item(itemIndex: Int) {
        val startY = -movedY
        movedY = Math.max(
            -itemMoveHeightMap[itemIndex]!!,
            -movedTotalHeight
        )
        //scrollTo(0, -movedY)
        val targetY = -movedY
        mScroller.startScroll(mScroller.finalX, startY, mScroller.finalX, targetY - startY)
        invalidate()
        //requestLayout()
    }

    fun updateCallback(mCallback: ICalcBelongedIndexCallback?) {
        this.mCallback = mCallback
    }

    private fun addContent(contentDataList: MutableList<ContentData>) {
        var index = 0
        for (contentDataItem in contentDataList) {
            val titleLayout =
                LayoutInflater.from(context).inflate(R.layout.layout_title, this, false)
            val tvTitle = titleLayout.findViewById<AppCompatTextView>(R.id.tv_title)
            tvTitle.text = contentDataItem.title

            addView(
                titleLayout,
                ConstraintLayout.LayoutParams(
                    ConstraintLayout.LayoutParams.WRAP_CONTENT,
                    ConstraintLayout.LayoutParams.WRAP_CONTENT
                ).apply {
                    topMargin = context.resources.getDimension(R.dimen.dp_10).toInt()
                    marginStart = context.resources.getDimension(R.dimen.dp_10).toInt()
                }
            )
            titleContentBorderMap[index++] = true

            val drawableRes = contentDataItem.drawableRes
            for (item in contentDataItem.contentList) {
                val contentLayout =
                    LayoutInflater.from(context).inflate(R.layout.layout_content, this, false)

                val llContent = contentLayout.findViewById<LinearLayoutCompat>(R.id.ll_content)
                llContent.setOnClickListener {
                    context.showToast("currentItem:${item}")
                }

                val ivContent = contentLayout.findViewById<AppCompatImageView>(R.id.iv_content)
                ivContent.setBackgroundResource(drawableRes)

                val tvContent = contentLayout.findViewById<AppCompatTextView>(R.id.tv_content)
                tvContent.text = item

                addView(
                    contentLayout,
                    ConstraintLayout.LayoutParams(
                        ConstraintLayout.LayoutParams.WRAP_CONTENT,
                        ConstraintLayout.LayoutParams.WRAP_CONTENT
                    ).apply {
                        topMargin = context.resources.getDimension(R.dimen.dp_10).toInt()
                    }
                )
                titleContentBorderMap[index++] = false
            }
        }
    }


    interface ICalcBelongedIndexCallback {
        fun calcBelongedIndex(belongedIndex: Int)
    }

    companion object {
        const val TAG = "ContentItemLayout"
        const val ITEMS_PER_ROW = 3
        const val MIN_SLIDE_DISTANCE = 5
    }

}